home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / c_news / 15 / line.c < prev    next >
C/C++ Source or Header  |  1989-04-04  |  15KB  |  521 lines

  1. /* -- File:     line.c                                                      *
  2.    --                                                                       *
  3.    -- Author:   Anthony Lander                                              *
  4.    -- Date:     January 10, 1989.                                           *
  5.    --                                                                       *
  6.    -- Description:                                                          *
  7.    --           This library contains a rather complete set of functions for*
  8.    --           creating and maintaining linked lists.                      *
  9.    --                                                                       */
  10.  
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <malloc.h>
  15. #include <memory.h>
  16. #include <string.h>
  17.  
  18. #include "f_prot.h"                 /* Prototypes for all functions         */
  19. #include "line.h"                   /* STRUCTs and #DEFINEs for LINE.C      */
  20.  
  21.  
  22.  
  23. struct _line *last_line = NULL;         /* The last line in the linked list */
  24. struct _line *first_line = NULL;        /* The first line in the list       */
  25.                                         /* Both NULL until initialized by   */
  26.                                         /* init_list()                      */
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47. /* ------------------------------------------------------------------------ */
  48. /* Function: Return the first line in the list                              */
  49. /* ------------------------------------------------------------------------ */
  50.  
  51. struct _line *get_first_line()
  52. {
  53.      return(first_line);
  54. }
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78. /* ------------------------------------------------------------------------ */
  79. /* Function: Return the last line in the list                               */
  80. /* ------------------------------------------------------------------------ */
  81.  
  82. struct _line *get_last_line()
  83. {
  84.      return(last_line);
  85. }
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109. /* ------------------------------------------------------------------------ */
  110. /* Function: Return a ptr to a line that's got space malloc()'ed for it     */
  111. /* ------------------------------------------------------------------------ */
  112.  
  113. /* -- Note:  string is set to NULL.  Length is set to 0.  Prev and next are *
  114.    --        set to NULL.                                                   *
  115.    --                                                                       *
  116.    -- takes:        nothing                                                 *
  117.    -- returns:      NULL if there's no more memory                          *
  118.    --               PTR to struct _line if a new line has been created      *
  119.    --                                                                       */
  120.  
  121. struct _line *get_new_line()
  122. {
  123.      struct _line *new_line;
  124.  
  125.      new_line = (struct _line *) malloc( sizeof(struct _line) );
  126.  
  127.     if(new_line == NULL)    {    /* malloc() failed                  */ 
  128.         return(NULL);
  129.     }
  130.  
  131.                             /* Otherwise, NULL all of the pointers          */
  132.      new_line->string = NULL;
  133.      new_line->length = 0;
  134.      new_line->next_line = NULL;
  135.      new_line->prev_line = NULL;
  136.  
  137.      return(new_line);
  138. }
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160. /* ------------------------------------------------------------------------ */
  161. /* Function: Insert a line after another line.                              */
  162. /* ------------------------------------------------------------------------ */
  163.  
  164. /* -- Takes:        insert, a ptr with string, length, max_length set       *
  165.    --               correctly.  after, a ptr to the line to add 'insert;    *
  166.    --               after.                                                  *
  167.    -- Returns:      None                                                    *
  168.    --                                                                       *
  169.    -- Notes:   This function will set up the prev_line and next_line        *
  170.    --          pointers so that the inserted line will fit correctly in the *
  171.    --          chain.  It will also fix the last_line pointer, if needed.   *
  172.    --                                                                       */
  173.  
  174. void insert_after_line(insert, after)
  175. struct _line *insert,                           /* line to insert           */
  176.              *after;                            /* line to insert it after  */
  177. {
  178.      /* -- if after is NULL, it means that we're creating the only line in  *
  179.         -- the list.  Thus, we don't make an uplink for insert.             *
  180.         --                                                                  */
  181.      if(after == NULL)   {
  182.           insert->prev_line = NULL;
  183.           insert->next_line = NULL;
  184.           first_line = insert;
  185.           last_line = insert;
  186.           return;
  187.      }
  188.  
  189.      /* -- otherwise, we're inserting after an already existing line.       *
  190.         -- Check to see whether we're the new last line, and adjust         *
  191.         -- accordingly.                                                     *
  192.         --                                                                  */
  193.      insert->prev_line = after;
  194.      insert->next_line = after->next_line;
  195.      after->next_line = insert;
  196.  
  197.      if(insert->next_line == NULL)      {
  198.           last_line = insert;
  199.      }
  200.      /* if NOT the last line in the list, then set after->next's prev_line */
  201.      else      {
  202.           (insert->next_line)->prev_line = insert;
  203.      }
  204. }
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227. /* ------------------------------------------------------------------------ */
  228. /* Function: Insert one line before another line                            */
  229. /* ------------------------------------------------------------------------ */
  230.  
  231. /* -- Takes:        insert, a ptr with string, length, max_length set       *
  232.    --               correctly.  before, a ptr to the line to add 'insert'   *
  233.    --               before.                                                 *
  234.    --                                                                       *
  235.    -- Returns:      None                                                    *
  236.    --                                                                       *
  237.    -- Notes:   This function will set up the prev_line and next_line        *
  238.    --          pointers so that the inserted line will fit correctly in the *
  239.    --          chain.  It will also fix the first_line pointer if needed.   *
  240.    --                                                                       */
  241.  
  242. void insert_before_line(insert, before)
  243. struct _line *insert,                     /* line to insert                 */
  244.              *before;                     /* line to insert 'insert' before */
  245. {
  246.  
  247.      /* -- if before is NULL then we're creating the only line in the list. *
  248.         -- Set up first_line and last_line, as well as insert's prev_line   *
  249.         -- and next_line links.                                             *
  250.         --                                                                  */
  251.      if(before == NULL)  {
  252.           insert->prev_line = NULL;
  253.           insert->next_line = NULL;
  254.           last_line = insert;
  255.           first_line = insert;
  256.           return;
  257.      }
  258.  
  259.  
  260.      /* -- otherwise we're in the middle, so set insert's next and prev     *
  261.         -- pointers like this....                                           *
  262.         --                                                                  */
  263.      insert->next_line = before;
  264.      insert->prev_line = before->prev_line;
  265.  
  266.  
  267.                                          /* set before's prev pointer       */
  268.      before->prev_line = insert;
  269.  
  270.      /* if (insert->prev_line) is NULL, then it's the new start of the list */
  271.      if(insert->prev_line == NULL)      {
  272.           first_line = insert;
  273.      }
  274.  
  275.          /* Otherwise, reset (insert->prev_line)->next_line's pointer       */
  276.      else {
  277.           (insert->prev_line)->next_line = insert;
  278.      }
  279.  
  280.                  /* Now set up (insert->prev_line)'s next_line link         */
  281.      if(insert->prev_line != NULL)
  282.           (insert->prev_line)->next_line = insert;
  283. }
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307. /* ------------------------------------------------------------------------ */
  308. /* Function: Delete a line from the list                                    */
  309. /* ------------------------------------------------------------------------ */
  310.  
  311. /* -- Takes:        line to delete                                          *
  312.    -- Returns:      nothing -- better be sure to pass a valid pointer!      *
  313.    --                                                                       *
  314.    -- Notes:   If you delete the first or last line, the first_ or last_    *
  315.    --          line pointers will get updated                               *
  316.    --                                                                       */
  317.  
  318. void delete_line(delete)
  319. struct _line *delete;
  320. {
  321.      /* -- SPECIAL CASE:    The first and/or last line of the list.         *
  322.         --                  These special cases are treated differently     *
  323.         --                  so that we can deal with thier NULL pointers    *
  324.         --                  in either prev_line, or next_line.              *
  325.         --                                                                  */
  326.      if(delete == first_line || delete == last_line)   {
  327.  
  328.           /* -- If we're the first line, and not the only line, then make   *
  329.              -- the next line the new first line.                           *
  330.              --                                                             */
  331.           if((delete == first_line) && (delete->next_line != NULL))
  332.                (delete->next_line)->prev_line = NULL;
  333.  
  334.           /* -- Test to see if we're (possibly also) the last line in the   *
  335.              -- list, but make sure we're not the only line in the list.    *
  336.              --                                                             */
  337.           if((delete == last_line) && (delete->prev_line != NULL))
  338.                (delete->prev_line)->next_line = NULL;
  339.      }
  340.  
  341.              /* OTHERWISE we're in the middle, so patch all links normally  */
  342.      else {
  343.           (delete->prev_line)->next_line = delete->next_line;
  344.           (delete->next_line)->prev_line = delete->prev_line;
  345.      }
  346.  
  347.      /* -- now free the structure, but first release the string space       *
  348.         -- if it's been allocated.                                          *
  349.         --                                                                  */
  350.  
  351.      if(delete->string != NULL)
  352.           free(delete->string);
  353.  
  354.  
  355.     /* See if we have to adjust first_line and last_line                    */
  356.     if(delete == first_line)
  357.         first_line = delete->next_line;
  358.  
  359.     if(delete == last_line)
  360.         last_line = delete->prev_line;
  361.  
  362.  
  363.      free(delete);
  364. }
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388. /* ------------------------------------------------------------------------ */
  389. /* Function: Delete all lines in the list                                   */
  390. /* ------------------------------------------------------------------------ */
  391.  
  392. /* -- Takes:        Nothing                                                 *
  393.    -- Returns:      Nothing                                                 *
  394.    --                                                                       *
  395.    -- Notes:   This goes through the list, starting at the top, and deletes *
  396.    --          all of the lines (and strings in lines) until it gets to the *
  397.    --          bottom.                                                      *
  398.    --                                                                       */
  399.  
  400. void delete_all_lines()
  401. {
  402.      while(first_line != NULL)      {
  403.           if(first_line->string != NULL)
  404.                free(first_line->string);
  405.  
  406.           free(first_line);
  407.           first_line = first_line->next_line;
  408.      }
  409. }
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433. /* ------------------------------------------------------------------------ */
  434. /* Function: Move a line before another line                                */
  435. /* ------------------------------------------------------------------------ */
  436.  
  437. /* -- Takes:        PTR to line to move.                                    *
  438.    --               PTR to line to move it before.                          *
  439.    -- Returns:      nothing.                                                *
  440.    --                                                                       *
  441.    -- Notes:   move_before just calls insert_before_line() and delete()     *
  442.    --                                                                       */
  443.  
  444. void move_before_line(move, before)
  445. struct _line *move,                 /* Line to move                         */
  446.              *before;               /* Line to move it before (ahead of)    */
  447. {
  448.      struct _line *temp;
  449.  
  450.      temp = get_new_line();
  451.      memcpy(temp, move, sizeof(struct _line));
  452.  
  453.          /* Now make a copy of move->string, 'cuz temp just has the address */
  454.      temp->string = malloc(strlen(move->string)+1);
  455.      strcpy(temp->string, move->string);
  456.  
  457.                          /* make temp's *_line links point to NULL          */
  458.      temp->prev_line = NULL;
  459.      temp->next_line = NULL;
  460.  
  461.     delete_line(move);
  462.     insert_before_line(temp, before);
  463. }
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489. /* ------------------------------------------------------------------------ */
  490. /* Function: Move a line after another line                                 */
  491. /* ------------------------------------------------------------------------ */
  492.  
  493. /* -- Takes:        PTR to line to move.                                    *
  494.    --               PTR to line to move it after.                           *
  495.    -- Returns:      nothing.                                                *
  496.    --                                                                       *
  497.    -- Notes:   move_after just calls insert_after_line() and delete()       *
  498.    --                                                                       */
  499.  
  500. void move_after_line(move, after)
  501. struct _line *move,                 /* line to move                         */
  502.              *after;                /* line to move after (follow)          */
  503. {
  504.      struct _line *temp;
  505.  
  506.      temp = get_new_line();
  507.      memcpy(temp, move, sizeof(struct _line));
  508.  
  509.       /* Now make a copy of move->string, because temp just has the address */
  510.      temp->string = malloc(strlen(move->string)+1);
  511.      strcpy(temp->string, move->string);
  512.  
  513.                              /* make temp's chains point to NULL            */
  514.      temp->prev_line = NULL;
  515.      temp->next_line = NULL;
  516.  
  517.     delete_line(move);
  518.     insert_after_line(temp, after);
  519. }
  520.  
  521.